package domain.entities;

import java.util.Date;
import java.util.List;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.hibernate.Criteria;

/**
 * A data access object (DAO) providing persistence and search support for
 * ProtocoloCompromisopais entities. Transaction control of the save(), update()
 * and delete() operations can directly support Spring container-managed
 * transactions or they can be augmented to handle user-managed Spring
 * transactions. Each of these methods provides additional information for how
 * to configure it for the desired type of transaction control.
 * 
 * @see domain.entities.ProtocoloCompromisopais
 * @author MyEclipse Persistence Tools
 */

public class ProtocoloCompromisopaisDAO extends HibernateDaoSupport {
	private static final Logger log = LoggerFactory
			.getLogger(ProtocoloCompromisopaisDAO.class);

	protected void initDao() {
		// do nothing
	}

	public void save(ProtocoloCompromisopais transientInstance) {
		log.debug("saving ProtocoloCompromisopais instance");
		try {
			getHibernateTemplate().save(transientInstance);
			log.debug("save successful");
		} catch (RuntimeException re) {
			log.error("save failed", re);
			throw re;
		}
	}

	public void delete(ProtocoloCompromisopais persistentInstance) {
		log.debug("deleting ProtocoloCompromisopais instance");
		try {
			getHibernateTemplate().delete(persistentInstance);
			log.debug("delete successful");
		} catch (RuntimeException re) {
			log.error("delete failed", re);
			throw re;
		}
	}

	public ProtocoloCompromisopais findById(
			domain.entities.ProtocoloCompromisopaisId id) {
		log.debug("getting ProtocoloCompromisopais instance with id: " + id);
		try {
			ProtocoloCompromisopais instance = (ProtocoloCompromisopais) getHibernateTemplate()
					.get("domain.entities.ProtocoloCompromisopais", id);
			return instance;
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	public List<ProtocoloCompromisopais> findByExample(
			ProtocoloCompromisopais instance) {
		log.debug("finding ProtocoloCompromisopais instance by example");
		try {
			List<ProtocoloCompromisopais> results = (List<ProtocoloCompromisopais>) getHibernateTemplate()
					.findByExample(instance);
			log.debug("find by example successful, result size: "
					+ results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by example failed", re);
			throw re;
		}
	}

	public List findByProperty(String propertyName, Object value) {
		log.debug("finding ProtocoloCompromisopais instance with property: "
				+ propertyName + ", value: " + value);
		try {
			String queryString = "from ProtocoloCompromisopais as model where model."
					+ propertyName + "= ?";
			return getHibernateTemplate().find(queryString, value);
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}


	public List findAll() {
        log.debug("finding all ProtocoloCompromisopais instances");
        try {
            String queryString = "from ProtocoloCompromisopais";
            return getHibernateTemplate().find(queryString);
        } catch (RuntimeException re) {
            log.error("find all failed", re);
            throw re;
        }
    }

    public List findCompromisoPaisByProtocoloId(String procoloid) {
        try {
            String queryString = "select pais from ProtocoloCompromisopais p inner join p.compromisopais as pais where protocoloid = '" + procoloid + "'" ;
            return getHibernateTemplate().find(queryString);
        } catch (RuntimeException re) {
            log.error("find all failed", re);
            throw re;
        }
    }

    /*select ps.milestone, avg(ps.duration)
        from protocolo_compromisopais pcp
        inner join protocolo p on p.id = pcp.protocoloid
        inner join protocolscorecard ps on ps.scorecardid = pcp.scorecardid
        where pcp.compromisopaisid = 1
        group by ps.milestone
        order by ps.scorecardorder*/

    public List<ScorecardReports> findScorecardForReports(Integer compromisopaisId, Integer therapeuticArea ) {
        try {
            List<ScorecardReports> result;
             Criteria  criteria = getSession().createCriteria(ProtocoloCompromisopais.class)
                    .createAlias("protocolo", "p", CriteriaSpecification.INNER_JOIN)
                    .createAlias("scorecard", "s", CriteriaSpecification.INNER_JOIN)
                    .createAlias("s.protocolscorecards", "ps", CriteriaSpecification.INNER_JOIN)
                    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                    .add(Restrictions.eq("compromisopais.id", compromisopaisId));

                     if(therapeuticArea != null &&!therapeuticArea.equals(0) )
                         criteria.add(Restrictions.eq("p.therapeuticArea.id", therapeuticArea));

                    criteria.setProjection(Projections.projectionList()
                            .add(Projections.property("ps.scorecardConfigurationid.id"), "id")
                            .add(Projections.property("ps.milestone"), "milestone")
                            .add(Projections.avg("ps.duration"), "duration")
                            .add(Projections.max("ps.duration"), "max")
                            .add(Projections.min("ps.duration"), "min")
                            .add(Projections.groupProperty("ps.milestone")
                    )).setResultTransformer(Transformers.aliasToBean(ScorecardReports.class))
                    .addOrder(Order.asc("ps.scorecardOrder"));

            result = criteria.list();


              return result;
        } catch (RuntimeException re) {
            log.error("find all failed", re);
            throw re;
        }
    }


    public List<Integer> findDurationById(Integer id ) {
        try {
            List<Integer> result;
            Criteria  criteria = getSession().createCriteria(ProtocoloCompromisopais.class)
                    .createAlias("protocolo", "p", CriteriaSpecification.INNER_JOIN)
                    .createAlias("scorecard", "s", CriteriaSpecification.INNER_JOIN)
                    .createAlias("s.protocolscorecards", "ps", CriteriaSpecification.INNER_JOIN)
                    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                    .add(Restrictions.eq("ps.scorecardConfigurationid.id", id));

            criteria.setProjection(Projections.projectionList()
                    .add(Projections.property("ps.duration"))
                    )
                    .addOrder(Order.asc("ps.duration"));

            result = criteria.list();



            return result;
        } catch (RuntimeException re) {
            log.error("find all failed", re);
            throw re;
        }
    }

    public ProtocoloCompromisopais getByProtocoloIdCompromisopaisId(String protocoloId, Integer compromisopaisId) {
        try {
            String queryString = "from ProtocoloCompromisopais where protocoloid = '" + protocoloId + "' and compromisopaisid = " + compromisopaisId;
            List list = getHibernateTemplate().find(queryString);
            return (ProtocoloCompromisopais)list.get(0);
        } catch (RuntimeException re) {
            log.error("find all failed", re);
            throw re;
        }
    }

	public ProtocoloCompromisopais merge(
			ProtocoloCompromisopais detachedInstance) {
		log.debug("merging ProtocoloCompromisopais instance");
		try {
			ProtocoloCompromisopais result = (ProtocoloCompromisopais) getHibernateTemplate()
					.merge(detachedInstance);
			log.debug("merge successful");
			return result;
		} catch (RuntimeException re) {
			log.error("merge failed", re);
			throw re;
		}
	}

	public void attachDirty(ProtocoloCompromisopais instance) {
		log.debug("attaching dirty ProtocoloCompromisopais instance");
		try {
			getHibernateTemplate().saveOrUpdate(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public void attachClean(ProtocoloCompromisopais instance) {
		log.debug("attaching clean ProtocoloCompromisopais instance");
		try {
			getHibernateTemplate().lock(instance, LockMode.NONE);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public static ProtocoloCompromisopaisDAO getFromApplicationContext(
			ApplicationContext ctx) {
		return (ProtocoloCompromisopaisDAO) ctx
				.getBean("ProtocoloCompromisopaisDAO");
	}

    public List<ProtocoloCompromisopais> getWithDataForCommitment(String protocoloID){
        List<ProtocoloCompromisopais> result = getSession().createCriteria(ProtocoloCompromisopais.class)
                .createAlias("compromisopais", "cp", CriteriaSpecification.INNER_JOIN)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .add(Restrictions.eq("protocolo.id", protocoloID))
                .add(Restrictions.disjunction()
                        .add(Restrictions.isNotNull("plannedFpfv"))
                        .add(Restrictions.isNotNull("plannedLpfv"))
                        .add(Restrictions.isNotNull("plannedLplv"))
                        .add(Restrictions.isNotEmpty("enrolledPatients"))
                        .add(Restrictions.isNotEmpty("objetivos"))
                )
                .addOrder(Order.asc("compromisopais"))
                .list();

        return result;
    }


}